package com.example.kmsealdemo.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.example.kmsealdemo.model.AttachmentForm;
import com.example.kmsealdemo.model.SealInfo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.ParseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import javax.servlet.ServletContext;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;


@Service
public class ISealdemoService implements SealdemoService {
    private static final Logger logger = LoggerFactory.getLogger(ISealdemoService.class);
    @Autowired
    private ServletContext context;

    private final ResourceLoader resourceLoader;

    public ISealdemoService(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public String getSeal(String base64Str) throws Exception {
        logger.info("=====================开始进行附件信息处理===================");
        // InputStream byteArrayPdf = new FileInputStream("D:\\Downloads\\测试文件.pdf");
        InputStream inputStream = null;
        ObjectMapper mapper = new ObjectMapper();
        List<List<SealInfo>> sealLists = mapper.readValue(base64Str, new TypeReference<List<List<SealInfo>>>() {
        });
        SealInfo firstSeal = sealLists.get(0).get(0);
        byte[] decodedBytes = Base64.getDecoder().decode(firstSeal.getPdfBase64());
        ByteArrayInputStream byteArrayPdf = new ByteArrayInputStream(decodedBytes);
        // 创建PDF reader和stamper
        PdfReader reader = new PdfReader(byteArrayPdf);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfStamper stamper = new PdfStamper(reader, baos);
        for (SealInfo sealInfo : sealLists.get(0)) {
            //获取操作的页面
            PdfContentByte over = stamper.getOverContent(sealInfo.getPosPage());
             /*// 3. 获取A4尺寸（纵向）
        Rectangle a4 = PageSize.A4;
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {
            // 获取当前页的原始尺寸
            Rectangle originalSize = reader.getPageSize(i);

            // 创建新的页面尺寸（A4）
            PdfDictionary pageDict = reader.getPageN(i);
            PdfArray mediaBox = pageDict.getAsArray(PdfName.MEDIABOX);

            // 修改为A4尺寸（单位：磅）
            mediaBox.set(2, new PdfNumber(a4.getWidth()));  // 宽度
            mediaBox.set(3, new PdfNumber(a4.getHeight())); // 高度
            // 可选：调整内容缩放以适配新尺寸
            PdfContentByte content = stamper.getOverContent(i);
            content.setLiteral("%%Scale to fit\n");
            content.addTemplate(stamper.getImportedPage(reader, i),
                    a4.getWidth() / originalSize.getWidth(),
                    0, 0,
                    a4.getHeight() / originalSize.getHeight(),
                    0, 0);
        }*/
            String filePath = "classpath:static/seal/seal.png";
            Resource resource = resourceLoader.getResource(filePath);
            // 获取文件输入流
            inputStream = resource.getInputStream();
            Image stamp = Image.getInstance(IOUtils.toByteArray(inputStream));
            // 设置印章位置,前后端分辨率不同导致印章位置有偏差,X,Y轴各减50
            stamp.setAbsolutePosition(sealInfo.getPosX() - 50, sealInfo.getPosY() - 50);
            // 设置图片大小
            stamp.scaleAbsolute(sealInfo.getWidth(), sealInfo.getHeight());
            // 添加印章到PDF
            over.addImage(stamp);
        }
        // 关闭资源
        stamper.close();
        reader.close();
        // 将生成的PDF写入响应输出流
        int size = baos.size();
        InputStream streamTran = new ByteArrayInputStream(baos.toByteArray());
        // firstSeal.setFdUrlHeard("http://192.168.14.76:9002/");// 测试
        firstSeal.setFdUrlHeard("http://192.168.14.115:9002/");// 生产
        String attIds = uploadAnnex(streamTran, firstSeal.getFdFilename(), firstSeal.getFdUrlHeard(), size);
        updateFileAnnex(firstSeal, attIds);
        // String Base64Str = Base64.getEncoder().encodeToString(baos.toByteArray());
        // FileOutputStream fos = new FileOutputStream("D:/Desktop/证书模板1.pdf");
        // fos.write(baos.toByteArray());
        // fos.close();
        if (null != inputStream) {
            inputStream.close();
        }
        if (null != baos) {
            baos.close();
        }
        if (null != stamper) {
            stamper.close();
        }
        if (null != byteArrayPdf) {
            byteArrayPdf.close();
        }
        streamTran.close();
        logger.info("=====================附件信息处理结束===================");
        return attIds;
    }

    //上传附件
    public String uploadAnnex(InputStream streamTran, String fileName, String fdUrlHeard, int size) throws IOException {
        logger.info("=====================开始进行附件上传===================");
        String fdId = "";
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(fdUrlHeard + "openapi/sys-attach/fileStream/upload");
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.addBinaryBody("fdFile", streamTran, ContentType.create("application/pdf"), fileName);
            builder.addTextBody("fdAnonymous", "true");
            builder.addTextBody("fdLoginName", "admin");
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity1 = response.getEntity();
                    if (entity1 != null) {
                        String responseBody = EntityUtils.toString(entity1);
                        logger.info("附件大小：{}", size);
                        logger.info("上传文件返回结果：{}", responseBody);
                        JSONObject parse = JSONObject.parseObject(responseBody);
                        if (parse.getBoolean("success")) {
                            JSONObject data = parse.getJSONObject("data");
                            fdId = data.getString("fdId");
                            String traceId = parse.getString("traceId");
                        } else {
                            throw new IOException(parse.getString("msg"));
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("上传附件失败了", e.getMessage());
            throw new RuntimeException("上传附件失败", e);
        }
        logger.info("=====================附件上传结束===================");
        return fdId;
    }

    public void updateFileAnnex(SealInfo sealInfo, String attIds) throws Exception {
        logger.info("=====================开始修改表单附件信息===================");
        JSONObject jsonAnnex = new JSONObject();
        JSONObject person = new JSONObject();
        JSONObject mechanisms = new JSONObject();
        JSONObject sysXForm = new JSONObject();
        JSONObject mainData = new JSONObject();
        List<AttachmentForm> attachment = new ArrayList<>();
        JSONObject attAnnex = new JSONObject();
        person.put("fdLoginName", sealInfo.getFdLoginName());//登录名
        jsonAnnex.put("fdId", sealInfo.getFdProjectId());//表单ID主键
        jsonAnnex.put("curUser", person);//当前用户
        AttachmentForm attachmentForm = new AttachmentForm();
        attachmentForm.setFdId(attIds);//附件ID
        attachmentForm.setFdFileName(sealInfo.getFdFilename());//附件名称
        attachmentForm.setFdEntityKey(sealInfo.getFdEntityKey());//附件KEY

        // attAnnex.put("fdId", attIds);//附件ID
        // attAnnex.put("fdFileName", sealInfo.getFdFilename());//附件名称
        // attAnnex.put("fdEntityKey", sealInfo.getFdEntityKey());//附件KEY
        sysXForm.put("mainData", mainData);
        mechanisms.put("sys-xform", sysXForm);
        jsonAnnex.put("mechanisms", mechanisms);
        attachment.add(attachmentForm);
        mechanisms.put("attachment", attachment);

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 构建请求URL
            String requestUrl = sealInfo.getFdUrlHeard() + "openapi/km-review/main/open/update";
            // 创建POST请求
            HttpPost httpPost = new HttpPost(requestUrl);
            // 设置JSON请求体
            String jsonBody = JSON.toJSONString(jsonAnnex);
            httpPost.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));
            httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");

            logger.info("发起更新请求，URL: {}, 请求体: {}", requestUrl, jsonBody);

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                HttpEntity responseEntity = response.getEntity();

                if (responseEntity == null) {
                    logger.error("请求失败: 响应体为空, 状态码: {}", statusCode);
                    throw new RuntimeException("服务端返回空响应");
                }

                String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                logger.info("响应状态码: {}, 响应体: {}", statusCode, responseBody);

                if (statusCode != HttpStatus.SC_OK) {
                    logger.error("请求失败: 非200状态码, URL: {}", requestUrl);
                    throw new RuntimeException("HTTP请求失败，状态码: " + statusCode);
                }

                JSONObject result = JSONObject.parseObject(responseBody);
                if (!result.getBooleanValue("success")) {
                    String errorMsg = "更新表单文档失败! " + result.getString("msg");
                    logger.error(errorMsg);
                    throw new RuntimeException(errorMsg);
                }

                // 成功时处理返回数据 (按需取消注释)
                // JSONObject data = result.getJSONObject("data");
                // String fdId = data.getString("fdId");
                // String traceId = result.getString("traceId");

            } catch (ParseException | IOException e) {
                logger.error("响应解析失败: {}", e.getMessage(), e);
                throw new RuntimeException("响应解析异常", e);
            }
        } catch (IOException e) {
            logger.error("HTTP请求异常: {}", e.getMessage(), e);
            throw new RuntimeException("网络请求异常", e);
        }
        logger.info("=====================修改表单附件信息结束===================");
    }
}
